package points

import (
	"ferry/global/orm"
	"ferry/models/goods"
	"ferry/models/points"
	"ferry/pkg/pagination"
	"ferry/tools"
	"ferry/tools/app"
	"fmt"
	"strconv"

	"github.com/gin-gonic/gin"
)

/*
  @Author : lanyulei
  @Desc : 积分相关API
*/

// AddPoints 添加用户积分
func AddPoints(c *gin.Context) {
	var req struct {
		UserId      int    `json:"user_id" binding:"required"`
		ProcessId   int    `json:"process_id" binding:"required"`
		WorkOrderId int    `json:"work_order_id" binding:"required"`
		Points      int    `json:"points" binding:"required"`
		Reason      string `json:"reason"`
		ProcessName string `json:"process_name"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, -1, err, "参数错误")
		return
	}

	// 开始事务
	tx := orm.Eloquent.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 查询或创建用户积分记录
	var userPoints points.UserPoints
	err := tx.Where("user_id = ?", req.UserId).First(&userPoints).Error
	if err != nil {
		// 如果用户没有积分记录，创建新记录
		userPoints = points.UserPoints{
			UserId:      req.UserId,
			TotalPoints: req.Points,
		}
		if err := tx.Create(&userPoints).Error; err != nil {
			tx.Rollback()
			app.Error(c, -1, err, "创建用户积分记录失败")
			return
		}
	} else {
		// 更新积分
		userPoints.TotalPoints += req.Points
		if err := tx.Save(&userPoints).Error; err != nil {
			tx.Rollback()
			app.Error(c, -1, err, "更新用户积分失败")
			return
		}
	}

	// 创建积分历史记录
	pointsHistory := points.PointsHistory{
		UserId:      req.UserId,
		ProcessId:   req.ProcessId,
		WorkOrderId: req.WorkOrderId,
		Points:      req.Points,
		Type:        1, // 获取积分
		Reason:      req.Reason,
		ProcessName: req.ProcessName,
	}
	if err := tx.Create(&pointsHistory).Error; err != nil {
		tx.Rollback()
		app.Error(c, -1, err, "创建积分历史记录失败")
		return
	}

	// 提交事务
	tx.Commit()

	app.OK(c, gin.H{
		"userId":      req.UserId,
		"points":      req.Points,
		"totalPoints": userPoints.TotalPoints,
	}, "添加积分成功")
}

// GetUserPoints 获取用户积分
func GetUserPoints(c *gin.Context) {
	userIdStr := c.Query("user_id")
	if userIdStr == "" {
		// 如果没有指定用户ID，获取当前登录用户的积分
		userIdStr = strconv.Itoa(tools.GetUserId(c))
	}

	userId, err := strconv.Atoi(userIdStr)
	if err != nil {
		app.Error(c, -1, err, "用户ID格式错误")
		return
	}

	var userPoints points.UserPoints
	if err := orm.Eloquent.Where("user_id = ?", userId).First(&userPoints).Error; err != nil {
		// 如果没有积分记录，返回0积分
		app.OK(c, gin.H{
			"user_id":      userId,
			"total_points": 0,
		}, "获取用户积分成功")
		return
	}

	app.OK(c, userPoints, "获取用户积分成功")
}

// PointsHistoryWithUser 积分历史记录包含用户信息
type PointsHistoryWithUser struct {
	points.PointsHistory
	UserName string `json:"user_name"` // 用户名称
	NickName string `json:"nick_name"` // 用户昵称
}

// GetPointsHistory 获取用户积分历史
func GetPointsHistory(c *gin.Context) {
	var (
		pointsHistoryList []PointsHistoryWithUser
		count             int
		pageIndex         = 1
		pageSize          = 20
	)

	currentUserId := tools.GetUserId(c)

	// 获取分页参数
	if page := c.DefaultQuery("page", "1"); page != "" {
		pageIndex, _ = strconv.Atoi(page)
	}
	if size := c.DefaultQuery("limit", "20"); size != "" {
		pageSize, _ = strconv.Atoi(size)
	}

	// 构建查询条件，关联用户表获取用户名称
	query := orm.Eloquent.Table("p_points_history").Select("p_points_history.*, sys_user.username as user_name, sys_user.nick_name")
	query = query.Joins("LEFT JOIN sys_user ON p_points_history.user_id = sys_user.user_id")
	countQuery := orm.Eloquent.Table("p_points_history").Joins("LEFT JOIN sys_user ON p_points_history.user_id = sys_user.user_id")

	// 获取查询参数
	userIdParam := c.DefaultQuery("user_id", "")
	userName := c.DefaultQuery("user_name", "")
	processName := c.DefaultQuery("process_name", "")
	startTime := c.DefaultQuery("start_time", "")
	endTime := c.DefaultQuery("end_time", "")
	pointsType := c.DefaultQuery("type", "")

	// 如果没有指定用户ID，默认查询当前用户
	if userIdParam == "" {
		query = query.Where("p_points_history.user_id = ?", currentUserId)
		countQuery = countQuery.Where("p_points_history.user_id = ?", currentUserId)
	} else if userIdParam == "all" {
		// 如果用户ID为'all'，查询所有用户（不添加用户ID过滤条件）
		// 不添加任何用户ID过滤条件
	} else {
		// 如果指定了用户ID，使用指定的用户ID
		query = query.Where("p_points_history.user_id = ?", userIdParam)
		countQuery = countQuery.Where("p_points_history.user_id = ?", userIdParam)
	}

	// 用户名称过滤
	if userName != "" {
		query = query.Where("sys_user.username LIKE ? OR sys_user.nick_name LIKE ?", "%"+userName+"%", "%"+userName+"%")
		countQuery = countQuery.Where("sys_user.username LIKE ? OR sys_user.nick_name LIKE ?", "%"+userName+"%", "%"+userName+"%")
	}

	// 流程名称过滤
	if processName != "" {
		query = query.Where("p_points_history.process_name LIKE ?", "%"+processName+"%")
		countQuery = countQuery.Where("process_name LIKE ?", "%"+processName+"%")
	}

	// 时间范围过滤
	if startTime != "" {
		query = query.Where("p_points_history.create_time >= ?", startTime)
		countQuery = countQuery.Where("create_time >= ?", startTime)
	}
	if endTime != "" {
		query = query.Where("p_points_history.create_time <= ?", endTime)
		countQuery = countQuery.Where("create_time <= ?", endTime)
	}

	// 积分类型过滤
	if pointsType != "" {
		query = query.Where("p_points_history.type = ?", pointsType)
		countQuery = countQuery.Where("type = ?", pointsType)
	}

	// 查询总数
	err := countQuery.Count(&count).Error
	if err != nil {
		app.Error(c, -1, err, "查询积分历史总数失败")
		return
	}

	// 查询积分历史列表
	err = query.
		Order("p_points_history.create_time desc").
		Offset((pageIndex - 1) * pageSize).
		Limit(pageSize).
		Find(&pointsHistoryList).Error
	if err != nil {
		app.Error(c, -1, err, "查询积分历史失败")
		return
	}

	// 构造分页结果
	result := pagination.Paginator{
		TotalCount: count,
		Page:       pageIndex,
		PerPage:    pageSize,
		Data:       &pointsHistoryList,
	}

	app.OK(c, result, "获取积分历史成功")
}

// GetPointsRanking 获取积分排行榜
func GetPointsRanking(c *gin.Context) {
	var (
		rankingList []struct {
			points.UserPoints
			Username string `json:"username"`
			Nickname string `json:"nickname"`
		}
		limit = 10
	)

	// 获取排行榜数量参数
	if limitStr := c.DefaultQuery("limit", "10"); limitStr != "" {
		limit, _ = strconv.Atoi(limitStr)
		if limit > 100 {
			limit = 100 // 限制最大查询数量
		}
	}

	// 查询积分排行榜
	err := orm.Eloquent.Table("p_user_points").
		Select("p_user_points.*, sys_user.username, sys_user.nick_name as nickname").
		Joins("left join sys_user on sys_user.user_id = p_user_points.user_id").
		Where("p_user_points.total_points > 0").
		Order("p_user_points.total_points desc").
		Limit(limit).
		Scan(&rankingList).Error
	if err != nil {
		app.Error(c, -1, err, "查询积分排行榜失败")
		return
	}

	app.OK(c, rankingList, "获取积分排行榜成功")
}

// GetExchangeGoods 获取可兑换商品列表
func GetExchangeGoods(c *gin.Context) {
	var (
		goodsList []goods.Goods
		count     int
		pageIndex = 1
		pageSize  = 20
	)

	// 获取分页参数
	if page := c.DefaultQuery("pageIndex", "1"); page != "" {
		pageIndex, _ = strconv.Atoi(page)
	}
	if size := c.DefaultQuery("pageSize", "20"); size != "" {
		pageSize, _ = strconv.Atoi(size)
	}

	// 查询总数（只查询上架商品）
	err := orm.Eloquent.Model(&goods.Goods{}).Where("status = 1 AND stock > 0").Count(&count).Error
	if err != nil {
		app.Error(c, -1, err, "查询商品总数失败")
		return
	}

	// 查询商品列表
	err = orm.Eloquent.Model(&goods.Goods{}).
		Where("status = 1 AND stock > 0").
		Order("create_time desc").
		Offset((pageIndex - 1) * pageSize).
		Limit(pageSize).
		Find(&goodsList).Error
	if err != nil {
		app.Error(c, -1, err, "查询商品列表失败")
		return
	}

	// 构造分页结果
	result := pagination.Paginator{
		TotalCount: count,
		Page:       pageIndex,
		PerPage:    pageSize,
		Data:       &goodsList,
	}

	app.OK(c, result, "获取商品列表成功")
}

// ExchangeGoods 兑换商品
func ExchangeGoods(c *gin.Context) {
	type ExchangeRequest struct {
		GoodsId int `json:"goods_id" binding:"required"`
	}

	var req ExchangeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		app.Error(c, -1, err, "参数错误")
		return
	}

	userId := tools.GetUserId(c)

	// 开启事务
	tx := orm.Eloquent.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 查询商品信息
	var goodsInfo goods.Goods
	err := tx.Where("id = ? AND status = 1 AND stock > 0", req.GoodsId).First(&goodsInfo).Error
	if err != nil {
		tx.Rollback()
		app.Error(c, -1, err, "商品不存在或已下架")
		return
	}

	// 查询用户积分
	var userPoints points.UserPoints
	err = tx.Where("user_id = ?", userId).First(&userPoints).Error
	if err != nil {
		tx.Rollback()
		app.Error(c, -1, err, "查询用户积分失败")
		return
	}

	// 检查积分是否足够
	if userPoints.TotalPoints < goodsInfo.Points {
		tx.Rollback()
		app.Error(c, -1, nil, "积分不足，无法兑换")
		return
	}

	// 扣减用户积分
	err = tx.Model(&userPoints).Update("total_points", userPoints.TotalPoints-goodsInfo.Points).Error
	if err != nil {
		tx.Rollback()
		app.Error(c, -1, err, "扣减积分失败")
		return
	}

	// 扣减商品库存
	err = tx.Model(&goodsInfo).Update("stock", goodsInfo.Stock-1).Error
	if err != nil {
		tx.Rollback()
		app.Error(c, -1, err, "扣减库存失败")
		return
	}

	// 记录积分变动历史
	pointsHistory := points.PointsHistory{
		UserId: userId,
		Points: -goodsInfo.Points,
		Type:   2, // 兑换商品消耗积分
		Reason: fmt.Sprintf("兑换-%s-商品", goodsInfo.Name),
	}
	err = tx.Create(&pointsHistory).Error
	if err != nil {
		tx.Rollback()
		app.Error(c, -1, err, "记录积分变动失败")
		return
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		app.Error(c, -1, err, "兑换失败")
		return
	}

	app.OK(c, nil, "兑换成功")
}
